Skip to content

Conversation

@ranuka-laksika
Copy link

@ranuka-laksika ranuka-laksika commented Nov 10, 2025

Fixes wso2/api-manager#4541

Issue URL: wso2/api-manager#4541

Problem

When importing an OpenAPI Definition for an existing API using the "Edit and Import" option in the Publisher Portal, the editor and import dialog remained open even after successfully saving the definition. This forced users to manually close both dialogs, creating a poor user experience.

Solution

Implemented a callback mechanism to properly manage dialog state between parent and child components. After a successful import save:

  1. The editor automatically closes
  2. The import dialog automatically closes
  3. The isImporting state is properly reset

Changes Made

  • Modified: portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/APIDefinition/ImportDefinition.jsx

    • Added onImportDialogClose prop to receive close callback from parent
    • Imported useEffect hook
    • Added useEffect to expose close dialog function to parent component
  • Modified: portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/APIDefinition/APIDefinition.jsx

    • Added closeImportDialog state variable to store the close function
    • Added setImportDialogClose method to receive the close function from child component
    • Modified updateSwaggerDefinition method to close editor and import dialog after successful import
    • Updated ImportDefinition component usage to pass onImportDialogClose callback prop

Build Information

  • Java 11 (Temurin-Hotspot at /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/11.0.29-7/x64)
  • Maven 3.6.3
  • Built component: portals/publisher
  • Generated artifact: portals/publisher/target/publisher.war (33 MB)

Artifacts Replaced

  • Frontend: Replaced publisher folder in wso2am-4.6.0/repository/deployment/server/webapps/
    1. Removed existing publisher folder
    2. Copied new publisher.war from build output
    3. Extracted to create new publisher folder

Testing

No testing required for frontend changes (as per workflow guidelines).

Modified wso2am Pack Download

The complete modified wso2am-4.6.0 pack is available as a GitHub Actions artifact.

🔗 Download from GitHub Actions

Artifact Details:

  • Name: wso2am-4.6.0-issue-52.zip
  • Size: 508 MB
  • How to Download:
    1. Click the link above
    2. Scroll to "Artifacts" section
    3. Download the zip file
    4. Extract and use directly

Contents: Complete wso2am pack with the updated Publisher portal artifact ready to use.

Summary by CodeRabbit

New Features

  • Import dialogs now automatically close after successful API definition import or update operations, streamlining the workflow and eliminating manual dialog dismissal steps for a more seamless user experience.

…mport

- Added mechanism to close ImportDefinition dialog from parent component
- Modified ImportDefinition.jsx to expose close function via onImportDialogClose prop
- Updated APIDefinition.jsx to store and call the close dialog function
- After successful import save, both editor and import dialog now close automatically
- Reset isImporting state to prevent subsequent issues

Fixes #52
@coderabbitai
Copy link

coderabbitai bot commented Nov 10, 2025

Walkthrough

Modified APIDefinition and ImportDefinition components to establish bidirectional communication for managing the import dialog lifecycle. APIDefinition now passes a callback setter to ImportDefinition, which registers a cancel function. Upon successful import/update, the stored callback is invoked to automatically close the import dialog.

Changes

Cohort / File(s) Summary
Import Dialog Lifecycle Management
portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/APIDefinition/APIDefinition.jsx
Added state field closeImportDialog to store dialog close callback. Introduced setImportDialogClose method (bound in constructor) to capture the close function from child component. Pass onImportDialogClose={this.setImportDialogClose} prop to ImportDefinition. After successful import/update, invoke stored closeImportDialog callback if available. In update Swagger flow, close editor and trigger import dialog close callback when import is in progress.
Import Dialog Cancellation Hook
portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/APIDefinition/ImportDefinition.jsx
Added useEffect to React imports. Added new prop onImportDialogClose to component signature. Introduced useEffect hook to register handleAPIDefinitionImportCancel callback via onImportDialogClose when provided, enabling parent-initiated dialog cancellation.

Sequence Diagram(s)

sequenceDiagram
    participant Parent as APIDefinition
    participant Child as ImportDefinition
    participant User as User

    User->>Parent: Click "Import Definition"
    Parent->>Child: Render with onImportDialogClose callback
    Child->>Child: useEffect: Register cancel function
    Child->>Parent: onImportDialogClose(handleAPIDefinitionImportCancel)
    Parent->>Parent: Store callback in closeImportDialog state
    
    User->>Child: Select "Edit and Import"
    User->>User: Make changes in editor
    User->>Child: Click "Import Content"
    Child->>Parent: Submit definition
    Parent->>Parent: Process import successfully
    Parent->>Parent: Invoke closeImportDialog callback
    Parent->>Child: Trigger handleAPIDefinitionImportCancel
    Child->>Child: Close import dialog
    Parent->>Parent: Close editor
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Straightforward callback registration pattern with minimal logic changes
  • Limited scope affecting two tightly-coupled components
  • Clear, repetitive pattern of parent-child state synchronization
  • Verify useEffect dependency array is correct in ImportDefinition
  • Confirm closeImportDialog callback is always safely invoked (null-check present)

Possibly related PRs

Suggested reviewers

  • lasanthaS
  • Krishanx92
  • tharikaGitHub
  • piyumaldk

Poem

🐰 A dialog that wanders, now finds its way home,
When "Edit and Import" completes, no more to roam—
Parent calls child with callbacks so neat,
Import dialog closes, the user's retreat! ✨

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main fix: closing the editor and import dialog after successful API definition import, which directly addresses the PR's primary objective.
Linked Issues check ✅ Passed The PR successfully implements both objectives from issue #4541: closing the editor after successful import and automatically closing the import dialog when the editor closes.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the import dialog and editor closure flow; no unrelated modifications were introduced.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud
Copy link

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/APIDefinition/ImportDefinition.jsx (1)

120-127: Consider adding exhaustive dependencies to useEffect.

The useEffect hook references handleAPIDefinitionImportCancel in its body but doesn't include it in the dependency array. While this works in practice (since isAsyncAPI is stable for a given API), it may trigger linting warnings.

Consider either:

  1. Adding handleAPIDefinitionImportCancel to the dependency array, or
  2. Wrapping handleAPIDefinitionImportCancel with useCallback to stabilize its reference

Example with useCallback:

+const handleAPIDefinitionImportCancel = useCallback(() => {
+    isAsyncAPI ? setAsyncAPIDefinitionImport(false) : setOpenAPIDefinitionImport(false);
+    inputsDispatcher({ action: 'inputValue', value: null });
+}, [isAsyncAPI]);

-const handleAPIDefinitionImportCancel = () => {
-    // eslint-disable-next-line no-unused-expressions
-    isAsyncAPI ? setAsyncAPIDefinitionImport(false) : setOpenAPIDefinitionImport(false);
-    inputsDispatcher({ action: 'inputValue', value: null });
-};

 // Expose close dialog function to parent component
 useEffect(() => {
     if (onImportDialogClose) {
-        onImportDialogClose(() => {
-            handleAPIDefinitionImportCancel();
-        });
+        onImportDialogClose(handleAPIDefinitionImportCancel);
     }
-}, [onImportDialogClose]);
+}, [onImportDialogClose, handleAPIDefinitionImportCancel]);
portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/APIDefinition/APIDefinition.jsx (1)

610-617: Add defensive null check before invoking callback.

The code checks if this.state.closeImportDialog exists at line 614, which is good. However, it's accessing state directly at line 615. While this works, consider destructuring state for consistency and readability.

Apply this diff for improved consistency:

+const { closeImportDialog } = this.state;
+
 // Close editor and import dialog after successful import
 if (this.state.isImporting) {
     this.setState({ openEditor: false, isImporting: false });
-    if (this.state.closeImportDialog) {
-        this.state.closeImportDialog();
+    if (closeImportDialog) {
+        closeImportDialog();
     }
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9eea9b0 and b0c2cdd.

📒 Files selected for processing (2)
  • portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/APIDefinition/APIDefinition.jsx (5 hunks)
  • portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/APIDefinition/ImportDefinition.jsx (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/APIDefinition/APIDefinition.jsx (1)
portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/APIDefinition/ImportDefinition.jsx (1)
  • ImportDefinition (65-501)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-product
🔇 Additional comments (5)
portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/APIDefinition/ImportDefinition.jsx (1)

18-18: LGTM: useEffect import added.

The import is necessary for the new lifecycle hook that registers the close callback with the parent component.

portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/APIDefinition/APIDefinition.jsx (4)

174-174: LGTM: State field for storing the close callback.

The closeImportDialog state field is properly initialized to store the child component's close function.


191-191: LGTM: Method binding in constructor.

The setImportDialogClose method is correctly bound to maintain proper this context.


526-532: LGTM: Callback registration method.

The implementation correctly receives and stores the close function from the ImportDefinition child component.


871-873: LGTM: Callback prop correctly passed to child.

The onImportDialogClose prop is properly passed to the ImportDefinition component, establishing the parent-child communication channel for dialog lifecycle management.

*/
export default function ImportDefinition(props) {
const { setSchemaDefinition, editAndImport } = props;
const { setSchemaDefinition, editAndImport, onImportDialogClose } = props;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add PropTypes validation for the new prop.

The onImportDialogClose prop is missing from the PropTypes definition at lines 503-505. Add validation to document the expected function signature.

Add this to the PropTypes definition:

 ImportDefinition.propTypes = {
     setSchemaDefinition: PropTypes.func.isRequired,
+    editAndImport: PropTypes.func,
+    onImportDialogClose: PropTypes.func,
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { setSchemaDefinition, editAndImport, onImportDialogClose } = props;
ImportDefinition.propTypes = {
setSchemaDefinition: PropTypes.func.isRequired,
editAndImport: PropTypes.func,
onImportDialogClose: PropTypes.func,
};
🤖 Prompt for AI Agents
In
portals/publisher/src/main/webapp/source/src/app/components/Apis/Details/APIDefinition/ImportDefinition.jsx
around line 66 and update the PropTypes block at lines 503-505: the new prop
onImportDialogClose is used but not declared in PropTypes; add a PropTypes entry
for onImportDialogClose (e.g., PropTypes.func or PropTypes.func.isRequired
depending on whether it must always be provided) and include a short comment
describing the expected function signature (no args or a callback with an
event/object) to document usage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Saving API Definition after “Edit and Import” does not redirect back to API Definition page

1 participant